﻿using System;
using System.Drawing;
using System.Globalization;
using DimensionsHelper.Common.Utils;

namespace DimensionsHelper.Common.Contracts.Excel;

public class ExcelStyleColor : IEquatable<ExcelStyleColor>
{

    private ExcelStyleColor(byte a, byte r, byte g, byte b)
    {
        A = a;
        R = r;
        G = g;
        B = b;
    }


    public ExcelStyleColor(byte r, byte g, byte b) : this(255, r, g, b)
    {
    }


    public byte A { get; }

    public byte R { get; }

    public byte G { get; }

    public byte B { get; }

    public static ExcelStyleColor Empty => new(0, 0, 0, 0);

    public override string ToString() => StringHelper.GetRgbString(R, G, B);


    private const int AlphaMask = unchecked((int)0xFF000000);
    private const int RedMask = 0x00FF0000;
    private const int GreenMask = 0x0000FF00;
    private const int BlueMask = 0x000000FF;


    public int ToArgb() => AlphaMask | (R << 16) | (G << 8) | B;


    public static ExcelStyleColor FromArgb(int value)
    {
        return new ExcelStyleColor(
            (byte)((value & AlphaMask) >> 24),
            (byte)((value & RedMask) >> 16),
            (byte)((value & GreenMask) >> 8), 
            (byte)(value & BlueMask)
        );
    }


    public static bool TryParse(string? value, out ExcelStyleColor color)
    {
        color = null!;
        
        if (string.IsNullOrEmpty(value) || value == "0" || value == "000000" || value == "00000000")
        {
            color = Empty;
            return true;
        }

        byte aValue = 255; // 默认不透明

        // Argb，截取后6位
        if (value!.Length == 8)
        {
            if (!byte.TryParse(value[..2], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out aValue))
            {
                return false;
            }
            // 去掉前两位Alpha值
            value = value[2..];
        }
        else if (value!.Length != 6)
        {
            return false;
        }

        string rStr = value[..2];
        string gStr = value[2..4];
        string bStr = value[4..];

        if (!byte.TryParse(rStr, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out byte rValue) ||
            !byte.TryParse(gStr, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out byte gValue) ||
            !byte.TryParse(bStr, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out byte bValue))
        {
            return false;
        }

        color = new ExcelStyleColor(aValue, rValue, gValue, bValue);
        return true;
    }


    public bool Equals(int value)
    {
        return ToArgb() == value;
    }


    public bool Equals(Color color)
    {
        return A == color.A && R == color.R && G == color.G && B == color.B;
    }


    public bool Equals(ExcelStyleColor? other)
    {
        if (other == null)
        {
            return false;
        }

        return other.A == A && other.R == R && other.G == G && other.B == B;
    }


    public override bool Equals(object? obj)
    {
        return obj is ExcelStyleColor styleColor && Equals(styleColor);
    }


    public override int GetHashCode()
    {
        return HashCode.Combine(A, R, G, B);
    }

    public static bool operator ==(ExcelStyleColor? left, ExcelStyleColor? right)
    {
        return ReferenceEquals(left, right) || left?.Equals(right) == true;
    }

    public static bool operator !=(ExcelStyleColor? left, ExcelStyleColor? right)
    {
        return !(left == right);
    }

    public static bool operator ==(ExcelStyleColor? left, int right)
    {
        return left?.Equals(right) == true;
    }

    public static bool operator !=(ExcelStyleColor? left, int right)
    {
        return !(left == right);
    }

    public static bool operator ==(ExcelStyleColor? left, Color right)
    {
        return left?.Equals(right) == true;
    }

    public static bool operator !=(ExcelStyleColor? left, Color right)
    {
        return !(left == right);
    }
}